import type { CLFormProps, CLFormActions, ComponentType } from "../types";
import { FormModel } from "./useFormModel";
const formModel = FormModel.getInstance();

/**
 * 暴露给cl-form使用者的方法
 */
export const FormMethods = (() => {
  let instance: Methods | null = null;
  class Methods implements CLFormActions {
    #propsData: CLFormProps = {
      formColumns: [],
    };

    /** 初始化默认表单值 */
    #initDefaultModelValue(component: ComponentType) {
      switch (component) {
        case "Input":
          return "";
        default:
          return undefined;
      }
    }

    /** 初始化默认组件属性 */
    #initDefaultComponentProps() {
      this.#propsData.formColumns = this.#propsData.formColumns.map(
        (formColumn) => {
          if (["InputNumber"].includes(formColumn.component)) {
            return formColumn;
          }
          return {
            ...formColumn,
            componentProps: {
              clearable: true,
              ...(formColumn.componentProps || {}),
            },
          } as any;
        }
      );
    }

    /** 写入使用者传入的默认值 */
    #setModel() {
      for (const { prop, defaultValue, component } of this.#propsData
        .formColumns) {
        formModel.model.value[prop] =
          defaultValue || this.#initDefaultModelValue(component);
      }
    }
    public init(propsData: CLFormProps) {
      this.#propsData = propsData;
      this.#initDefaultComponentProps();
      formModel.setProps(propsData);
      this.#setModel();
    }
    public async load() {}
    public getValue() {
      return formModel.model.value;
    }
    public setValue(newValue: Recordable, type: "assign" | "cover" = "assign") {
      if (!isObject(newValue)) {
        warn("cl-form的setValue方法", "该操作无效，因为只支持写入对象");
        return;
      }
      if (type === "assign") {
        Object.assign(formModel.model.value, newValue);
      } else if (type === "cover") {
        formModel.model.value = newValue;
      }
    }
  }

  return {
    getInstance() {
      return instance || (instance = new Methods());
    },
  };
})();
